﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Text;
using System.IO;

namespace THO7_Team8.Dialogs
{
    public partial class OcrTestsetDialog : Form
    {
        InstalledFontCollection fonts;
        private String _letterstocreate;
        private String folderpath;
        private FontFamily _selectedFont;
        public String lettersToCreate
        {
            get { return _letterstocreate; }
            set { _letterstocreate = value; }
        }
        public OcrTestsetDialog()
        {
            InitializeComponent();
            fonts = new InstalledFontCollection();
            foreach (FontFamily f in fonts.Families)
            {
                comboBox1.Items.Add(f.Name);
            }
            comboBox1.SelectedIndex = 0;
            //comboBox1.
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.UseWaitCursor = true;
            lettersToCreate = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            _selectedFont = (FontFamily)fonts.Families.GetValue(comboBox1.SelectedIndex);
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "Folder to save the new testset in";
            fbd.ShowNewFolderButton = true;
            fbd.RootFolder = Environment.SpecialFolder.MyPictures;
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                folderpath = fbd.SelectedPath;
                this.groupBox1.Enabled = false;
                this.groupBox2.Enabled = false;
                backgroundWorker1.RunWorkerAsync();
            }
            //pictureBox1.Image = DrawLetter(c, (FontFamily)fonts.Families.GetValue(comboBox1.SelectedIndex), FontStyle.Bold);
        }
        
        private Bitmap DrawLetter(Char letter, FontFamily fontFamily, FontStyle fontStyle)
        {
            Bitmap b = new Bitmap(300, 300);
            Graphics myg = Graphics.FromImage(b);
            myg.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(0, 0), b.Size));

            float width = ((float)b.Width);
            float height = ((float)b.Height);

            float emSize = height;

            Font font = new Font(fontFamily, emSize, fontStyle);

            font = FindBestFitFont(myg, letter.ToString(), font, b.Size);

            SizeF size = myg.MeasureString(letter.ToString(), font);
            myg.DrawString("" + letter, font, new SolidBrush(Color.Black), 0, 0);
            return Crop(b);
        }

        private Font FindBestFitFont(Graphics g, String text, Font font, Size proposedSize)
        {
            // Compute actual size, shrink if needed
            while (true)
            {
                SizeF size = g.MeasureString(text, font);
                

                // It fits, back out
                if (size.Height <= proposedSize.Height &&
                     size.Width <= proposedSize.Width) { return font; }

                // Try a smaller font (90% of old size)
                Font oldFont = font;
                font = new Font(font.Name, (float)(font.Size * .9), font.Style);
                oldFont.Dispose();
            }
        }
        private Bitmap Crop(Bitmap bmp)
        {
            int w = bmp.Width, h = bmp.Height;

            Func<int, bool> allWhiteRow = row =>
            {
                for (int i = 0; i < w; ++i)
                    if (bmp.GetPixel(i, row).R != 255)
                        return false;
                return true;
            };

            Func<int, bool> allWhiteColumn = col =>
            {
                for (int i = 0; i < h; ++i)
                    if (bmp.GetPixel(col, i).R != 255)
                        return false;
                return true;
            };

            int topmost = 0;
            for (int row = 0; row < h; ++row)
            {
                if (allWhiteRow(row))
                    topmost = row;
                else break;
            }

            int bottommost = 0;
            for (int row = h - 1; row >= 0; --row)
            {
                if (allWhiteRow(row))
                    bottommost = row;
                else break;
            }

            int leftmost = 0, rightmost = 0;
            for (int col = 0; col < w; ++col)
            {
                if (allWhiteColumn(col))
                    leftmost = col;
                else
                    break;
            }

            for (int col = w - 1; col >= 0; --col)
            {
                if (allWhiteColumn(col))
                    rightmost = col;
                else
                    break;
            }
            if (rightmost == 0) rightmost = bmp.Width - 1;
            if (bottommost == 0) bottommost = bmp.Height - 1;

            int croppedWidth = rightmost - leftmost;
            int croppedHeight = bottommost - topmost;
            try
            {
                Bitmap target = new Bitmap(croppedWidth, croppedHeight);
                using (Graphics g = Graphics.FromImage(target))
                {
                    g.DrawImage(bmp,
                      new RectangleF(0, 0, croppedWidth, croppedHeight),
                      new RectangleF(leftmost, topmost, croppedWidth, croppedHeight),
                      GraphicsUnit.Pixel);
                }
                return target;
            }
            catch (Exception ex)
            {
                throw new Exception(
                  string.Format("Values are topmost={0} btm={1} left={2} right={3}", topmost, bottommost, leftmost, rightmost),
                  ex);
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            int numberOfItems = this.lettersToCreate.Length;
            int currentItem = 0;
            foreach (Char theLetter in this.lettersToCreate)
            {
                DrawLetter(theLetter, _selectedFont, FontStyle.Bold).Save(folderpath + "\\" + theLetter + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                currentItem++;
                worker.ReportProgress((int)(((double)currentItem / (double)numberOfItems) * 100));
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Console.WriteLine(e.ProgressPercentage);
            progressBar1.Value = e.ProgressPercentage;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.groupBox1.Enabled = true;
            this.groupBox2.Enabled = true;
            this.UseWaitCursor = false;
        }
        private void pictureBox2_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(
                    DataFormats.FileDrop);
                foreach (string file in files)
                {
                    FileInfo fileInfo = new FileInfo(file);
                    if (fileInfo.Extension.ToLower() == ".jpg" || fileInfo.Extension.ToLower() == ".bmp" || fileInfo.Extension.ToLower() == ".png")
                    {
                        Console.WriteLine("OCR file: " + file);
                        Bitmap InputImage = new Bitmap(file);
                        NormalLetterDetection n = new NormalLetterDetection("nld");
                        n.runStandAlone = false;
                        n.DoAlgorithm(Crop(InputImage));
                        pictureBox2.Image = Crop(InputImage);
                        textBox1.Text = n.detectedPoints;
                        textBox2.Text = "" + n.detectedCharacter;
                        
                    }
                }
            }
        }

        private void ExtendedForm_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Move;
            else
                e.Effect = DragDropEffects.None;
        }

    }
}
